#include <BytesEndian.h>
#include <arpa/inet.h>
#include <cstring>
#include <netinet/in.h>
#include <string>
#include <sys/un.h>
namespace xncc {
namespace foundation {
    class SocketOpt
    {
      public:
        static auto createNonblockingOrDie(sa_family_t family, int protocol = IPPROTO_TCP, int type = SOCK_STREAM)
            -> int;
        static auto createOrDie(sa_family_t family, int protocol = IPPROTO_TCP, int type = SOCK_STREAM) -> int;
        static void setNonBlockAndCloseOnExec(int sockfd);
        static auto read(int sockfd, void* buf, size_t count) -> ssize_t;
        static auto readv(int sockfd, const struct iovec* iov, int iovcnt) -> ssize_t;
        static auto write(int sockfd, const void* buf, size_t count) -> ssize_t;
        static void close(int sockfd);
        static void shutdownWrite(int sockfd);
        static auto toIpPort(const struct sockaddr* addr) -> std::string;
        static auto toIp(const struct sockaddr* addr) -> std::string;
        static auto getSocketError(int sockfd) -> int;
        static auto sockaddr_cast(const struct sockaddr_in* addr) -> const struct sockaddr*;
        static auto sockaddr_cast(const struct sockaddr_in6* addr) -> const struct sockaddr*;
        static auto sockaddr_cast(struct sockaddr_in6* addr) -> struct sockaddr*;
        static auto sockaddr_cast(struct sockaddr_in* addr) -> struct sockaddr*;
        static auto sockaddr_cast(const struct sockaddr_un* addr) -> const struct sockaddr*;
        static auto sockaddr_cast(struct sockaddr_un* addr) -> struct sockaddr*;
        static auto sockaddr_in_cast(const struct sockaddr* addr) -> const struct sockaddr_in*;
        static auto sockaddr_in6_cast(const struct sockaddr* addr) -> const struct sockaddr_in6*;
        static auto sockaddr_un_cast(const struct sockaddr* addr) -> const struct sockaddr_un*;
        static auto isSelfConnect(int sockfd) -> bool;
        static auto getLocalAddrStr(int sockfd) -> std::string;
        static auto getPeerAddrStr(int sockfd) -> std::string;
        static void setReuseAddr(bool on, int sockfd);
        static void setReusePort(bool on, int sockfd);
        static void setTcpKeepAlive(bool on, int sockfd);

      private:
        static struct sockaddr_un getLocalAddr(int sockfd);
        static struct sockaddr_un getPeerAddr(int sockfd);
        static std::string        toStr(const struct sockaddr* addr);
    };
}  // namespace foundation
}  // namespace xncc